package com.fjwt.gz.service.impl;

import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjwt.gz.core.cache.RedisUtil;
import com.fjwt.gz.core.constants.CS;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.db.base.BaseAgentApp;
import com.fjwt.gz.db.dto.AgentAppDTO;
import com.fjwt.gz.db.entity.AgentAppEntity;
import com.fjwt.gz.db.entity.AgentInfoEntity;
import com.fjwt.gz.db.entity.SysConfig;
import com.fjwt.gz.db.vo.AgentAppVO;
import com.fjwt.gz.service.mapper.AgentAppMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * <p>
 * 机构小程序表 服务实现类
 * </p>
 *
 * @author shiyonghao
 * @since 2025-04-09
 */
@Slf4j
@Service
public class AgentAppService extends ServiceImpl<AgentAppMapper, AgentAppEntity> {

    @Autowired
    private AgentInfoService agentInfoService;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private AgentAppService agentAppService;

    @Autowired
    private AgentAppMapper agentAppMapper;

    /**
     * 列表
     * @param iPage
     * @param agentAppDTO
     * @return
     */
    public IPage<AgentAppVO> page (IPage iPage, AgentAppDTO agentAppDTO) {
        if (StrUtil.isNotBlank(agentAppDTO.getAgentNo())) {
            List<String> allSubAgentNo = agentInfoService.queryAllSubAgentNo(agentAppDTO.getAgentNo());
            agentAppDTO.setAgentNoList(allSubAgentNo);
        }

        IPage<AgentAppVO> page = baseMapper.page(iPage, agentAppDTO);
        if(!page.getRecords().isEmpty()){
            for (AgentAppVO record : page.getRecords()) {
                AgentInfoEntity agentInfo = agentInfoService.getAgentInfo(record.getAgentNo());
                if (ObjectUtils.isNotEmpty(agentInfo)) {
                    record.setAgentName(agentInfo.getAgentName());
                }
            }
        }
        return page;
    }

    /**
     * 新增
     * @param agentAppDTO
     */
    @Transactional
    public void add(AgentAppDTO agentAppDTO, BaseAgentApp baseAgentApp) {

        if (ObjectUtils.isEmpty(agentAppDTO.getAppId())) {
            throw new BizException("请输入appid");
        }
        check(agentAppDTO, baseAgentApp);
        if (ObjectUtils.isEmpty(baseAgentApp.getAppSecret())) {
            throw new BizException("请输入appSecret");
        }
        if (ObjectUtils.isEmpty(agentAppDTO.getAgentNo())) {
            throw new BizException("请选择归属机构");
        }
        if (ObjectUtils.isEmpty(agentAppDTO.getType())) {
            throw new BizException("请选择应用类型");
        }
        if (ObjectUtils.isEmpty(agentAppDTO.getIsDefault())) {
            throw new BizException("请选择是否默认应用");
        }
        if (agentAppDTO.getType() == Constants.AGENT_APP_TYPE.WX_OFFICIAL) {
            if (ObjectUtils.isEmpty(baseAgentApp.getToken())) {
                throw new BizException("请输入微信公众号令牌");
            }
            if (ObjectUtils.isEmpty(baseAgentApp.getAesKey())) {
                throw new BizException("请输入微信公众号消息加解密密钥");
            }
        }

        AgentInfoEntity agentInfo = agentInfoService.getAgentInfo(agentAppDTO.getAgentNo());
        if(ObjectUtils.isEmpty(agentInfo)){
            throw new BizException("所选机构不存在");
        }

        // 查询该appid是否已配置
        AgentAppEntity agentApp = baseMapper.selectOne(AgentAppEntity.gw().eq(AgentAppEntity::getAppId, agentAppDTO.getAppId()));
        if(ObjectUtils.isNotEmpty(agentApp)){
            throw new BizException("该应用已被配置");
        }

        AgentAppEntity agentAppEntity = new AgentAppEntity();
        BeanUtils.copyProperties(agentAppDTO, agentAppEntity);
        agentAppEntity.setAgentNo1(agentInfo.getAgentNo1());
        agentAppEntity.setAgentNo2(agentInfo.getAgentNo2());
        agentAppEntity.setAgentNo3(agentInfo.getAgentNo3());
        agentAppEntity.setAgentNo4(agentInfo.getAgentNo4());
        agentAppEntity.setIsDeleted(0);

        SysConfig sysConfig = sysConfigService.getById(agentAppEntity.getAppId());
        if (ObjectUtils.isEmpty(sysConfig)) {
            sysConfig = new SysConfig();
            sysConfig.setConfigKey(agentAppDTO.getAppId());
            sysConfig.setConfigName(agentAppDTO.getName());
            sysConfig.setConfigDesc(agentAppDTO.getName());
            sysConfig.setConfigVal(JSONObject.toJSONString(baseAgentApp));
            if (agentAppDTO.getType() == Constants.AGENT_APP_TYPE.WX_OFFICIAL) {
                sysConfig.setGroupKey(Constants.AGENT_APP_GROUP_KEY_MAP.get(Constants.AGENT_APP_TYPE.WX_OFFICIAL));
                sysConfig.setGroupName(Constants.AGENT_APP_GROUP_NAME_MAP.get(Constants.AGENT_APP_TYPE.WX_OFFICIAL));
            } else if (agentAppDTO.getType() == Constants.AGENT_APP_TYPE.WX_LITE) {
                sysConfig.setGroupKey(Constants.AGENT_APP_GROUP_KEY_MAP.get(Constants.AGENT_APP_TYPE.WX_LITE));
                sysConfig.setGroupName(Constants.AGENT_APP_GROUP_NAME_MAP.get(Constants.AGENT_APP_TYPE.WX_LITE));
            }
            sysConfig.setType(Constants.SYS_CONFIG_TYPE.TEXT);
            sysConfigService.save(sysConfig);
        }else {
            sysConfig.setConfigName(agentAppDTO.getName());
            sysConfig.setConfigDesc(agentAppDTO.getName());
            sysConfig.setConfigVal(JSONObject.toJSONString(baseAgentApp));
            sysConfigService.updateById(sysConfig);
        }

        if (CS.YES == agentAppEntity.getIsDefault()) {
            // 修改机构下其他同类型应用为非默认
            this.lambdaUpdate()
                    .eq(AgentAppEntity::getAgentNo, agentAppEntity.getAgentNo())
                    .eq(AgentAppEntity::getType, agentAppEntity.getType())
                    .eq(AgentAppEntity::getIsDeleted, CS.NO)
                    .eq(AgentAppEntity::getIsDefault, CS.YES)
                    .set(AgentAppEntity::getIsDefault, CS.NO)
                    .update();
        }
        baseMapper.insert(agentAppEntity);
        //放置缓存
        RedisUtil.setString(CS.getPrivacyService(agentAppEntity.getAppId()), JSON.toJSONString(agentAppEntity));

        Collection<String> keys = RedisUtil.keys(CS.getCacheKeyApplicationAgent(agentAppEntity.getAgentNo(), agentAppDTO.getType(), "*"));
        if (ObjectUtils.isNotEmpty(keys)) {
            keys.forEach(RedisUtil::del);
        }
    }

    /**
     * 修改
     * @param agentAppDTO
     */
    @Transactional
    public void update(AgentAppDTO agentAppDTO, BaseAgentApp baseAgentApp) {
        if (ObjectUtils.isEmpty(agentAppDTO.getAgentAppId())) {
            throw new BizException("请选择要修改的数据");
        }
        check(agentAppDTO, baseAgentApp);

        AgentAppEntity agentAppEntity = baseMapper.selectById(agentAppDTO.getAgentAppId());
        if (ObjectUtils.isEmpty(agentAppEntity)) {
            throw new BizException("所选数据异常，请重试");
        }

        // 查询该appid是否已配置
        agentAppEntity.setName(agentAppDTO.getName());
        agentAppEntity.setImgUrl(agentAppDTO.getImgUrl());
        agentAppEntity.setRemark(agentAppDTO.getRemark());
        agentAppEntity.setIsDeleted(agentAppDTO.getIsDeleted());
        agentAppEntity.setPrivacyPolicy(agentAppDTO.getPrivacyPolicy());
        agentAppEntity.setServiceAgreement(agentAppDTO.getServiceAgreement());
        agentAppEntity.setScoreRule(agentAppDTO.getScoreRule());

        if (CS.YES == agentAppEntity.getIsDefault()) {
            // 修改机构下其他同类型应用为非默认
            this.lambdaUpdate()
                    .eq(AgentAppEntity::getAgentNo, agentAppEntity.getAgentNo())
                    .eq(AgentAppEntity::getType, agentAppEntity.getType())
                    .eq(AgentAppEntity::getIsDeleted, CS.NO)
                    .eq(AgentAppEntity::getIsDefault, CS.YES)
                    .set(AgentAppEntity::getIsDefault, CS.NO)
                    .update();
        }

        baseMapper.updateById(agentAppEntity);
        //放置缓存
        RedisUtil.setString(CS.getPrivacyService(agentAppEntity.getAppId()), JSON.toJSONString(agentAppEntity));
        SysConfig sysConfig = sysConfigService.getById(agentAppEntity.getAppId());
        if (ObjectUtils.isEmpty(sysConfig)) {
            sysConfig = new SysConfig();
            sysConfig.setConfigKey(agentAppDTO.getAppId());
            sysConfig.setConfigName(agentAppDTO.getName());
            sysConfig.setConfigDesc(agentAppDTO.getName());
            sysConfig.setConfigVal(JSONObject.toJSONString(baseAgentApp));
            if (agentAppDTO.getType() == Constants.AGENT_APP_TYPE.WX_OFFICIAL) {
                sysConfig.setGroupKey(Constants.AGENT_APP_GROUP_KEY_MAP.get(Constants.AGENT_APP_TYPE.WX_OFFICIAL));
                sysConfig.setGroupName(Constants.AGENT_APP_GROUP_NAME_MAP.get(Constants.AGENT_APP_TYPE.WX_OFFICIAL));
            }else if (agentAppDTO.getType() == Constants.AGENT_APP_TYPE.WX_LITE) {
                sysConfig.setGroupKey(Constants.AGENT_APP_GROUP_KEY_MAP.get(Constants.AGENT_APP_TYPE.WX_LITE));
                sysConfig.setGroupName(Constants.AGENT_APP_GROUP_NAME_MAP.get(Constants.AGENT_APP_TYPE.WX_LITE));
            }
            sysConfig.setType(Constants.SYS_CONFIG_TYPE.TEXT);
            sysConfigService.save(sysConfig);
        }else {
            sysConfig.setConfigName(agentAppDTO.getName());
            sysConfig.setConfigDesc(agentAppDTO.getName());
            sysConfigService.updateById(sysConfig);
        }

        RedisUtil.del(CS.getCacheKeyApplication(agentAppEntity.getAppId()));
        Collection<String> keys = RedisUtil.keys(CS.getCacheKeyApplicationAgent(agentAppEntity.getAgentNo(), agentAppDTO.getType(), "*"));
        if (ObjectUtils.isNotEmpty(keys)) {
            keys.forEach(RedisUtil::del);
        }
    }

    /**
     * 参数检查
     * @param agentAppDTO
     */
    private static void check(AgentAppDTO agentAppDTO, BaseAgentApp baseAgentApp) {

        if (ObjectUtils.isEmpty(agentAppDTO.getName())) {
            throw new BizException("请输入应用名称");
        }
        if (ObjectUtils.isEmpty(agentAppDTO.getImgUrl())) {
            throw new BizException("请上传应用二维码图片");
        }
        if (agentAppDTO.getType() == Constants.AGENT_APP_TYPE.WX_OFFICIAL) {
            if (ObjectUtils.isEmpty(baseAgentApp.getAuthUrl())) {
                throw new BizException("请输入公众号获取open_id配置的url");
            }
            if (ObjectUtils.isEmpty(baseAgentApp.getOriginalId())) {
                throw new BizException("请输入微信公众号原始ID");
            }
            if (ObjectUtils.isEmpty(baseAgentApp.getEncryptType())) {
                throw new BizException("请选择公众号消息加解密方式");
            }
        }else if (agentAppDTO.getType() == Constants.AGENT_APP_TYPE.WX_LITE) {
//            if (ObjectUtils.isEmpty(baseAgentApp.getThumbMediaId())) {
//                throw new BizException("请上传素材图片");
//            }
        }
    }

    /**
     * 详情
     * @param agentAppDTO
     */
    public AgentAppVO detail(AgentAppDTO agentAppDTO) {
        if (ObjectUtils.isEmpty(agentAppDTO.getAgentAppId())){
            throw new BizException("请选择要查询的数据");
        }
        AgentAppEntity agentAppEntity = baseMapper.selectById(agentAppDTO.getAgentAppId());
        AgentAppVO agentAppVO = new AgentAppVO();
        if (ObjectUtils.isNotEmpty(agentAppEntity)) {
            BeanUtils.copyProperties(agentAppEntity, agentAppVO);
            // 查询秘钥信息
            BaseAgentApp agentApp = this.getAgentApp(agentAppVO.getAppId());
            AgentInfoEntity agentInfo = agentInfoService.getAgentInfo(agentAppVO.getAgentNo());
            if (ObjectUtils.isNotEmpty(agentInfo)) {
                agentAppVO.setAgentName(agentInfo.getAgentName());
            }
            agentAppVO.setThumbMediaId(agentApp.getThumbMediaId());
            agentAppVO.setAuthUrl(agentApp.getAuthUrl());
            agentAppVO.setOriginalId(agentApp.getOriginalId());
            agentAppVO.setEncryptType(agentApp.getEncryptType());
            agentAppVO.setAppSecret(DesensitizedUtil.idCardNum(agentApp.getAppSecret(), 3, 3));
            agentAppVO.setToken(DesensitizedUtil.idCardNum(agentApp.getToken(), 3, 3));
            agentAppVO.setAesKey(DesensitizedUtil.idCardNum(agentApp.getAesKey(), 3, 3));
        }

        return agentAppVO;
    }

    /**
     * 查询机构小程序信息
     * @param agentNo
     * @param appid
     * @return
     */
    public List<AgentAppVO> getAgentNoApp(String agentNo, Integer type, String appid) {
        List<AgentAppVO> agentAppVOs = new ArrayList<>();
        // 查缓存
        String cacheKeyApplicationAgent = CS.getCacheKeyApplicationAgent(agentNo, type, appid);
        if (ObjectUtils.isEmpty(appid)) {
            cacheKeyApplicationAgent = CS.getCacheKeyApplicationAgent(agentNo, type, "*");
        }
        Collection<String> keys = RedisUtil.keys(cacheKeyApplicationAgent);
        // 缓存为空查数据库
        if (ObjectUtils.isEmpty(keys)) {
            agentAppVOs = baseMapper.selectByAgentNoAndTypeAndAppid(agentNo, type, appid);
            // 数据库存在放入缓存
            if (ObjectUtils.isNotEmpty(agentAppVOs)) {
                agentAppVOs.forEach(item -> RedisUtil.set(CS.getCacheKeyApplicationAgent(item.getAgentNo(), item.getType(), item.getAppId()), item));
            }
        }else {
            for (String key : keys) {
                agentAppVOs.add(RedisUtil.getObject(key, AgentAppVO.class));
            }
        }
        return agentAppVOs;
    }

    /**
     * 查询机构小程序及上级小程序信息
     * @param agentNo
     * @param appid
     * @return
     */
    public List<AgentAppVO> getAgentNoAndTopApp(String agentNo, Integer type, String appid) {
        List<AgentAppVO> agentNoAppList = new ArrayList<>();
        // 查询当前机构和上级机构信息
        List<AgentInfoEntity> agentInfoList = new ArrayList<>();
        agentInfoService.queryAllTopAgentNo(agentInfoList, agentNo);
        for (AgentInfoEntity agentInfoEntity : agentInfoList) {
            // 查询上级机构小程序信息
            agentNoAppList.addAll(getAgentNoApp(agentInfoEntity.getAgentNo(), type, appid));
        }
        return agentNoAppList;
    }

    /**
     * 查询小程序秘钥信息
     * @param appid
     * @return
     */
    public BaseAgentApp getAgentApp(String appid) {
        // 查缓存
        String cacheKeyApplication = CS.getCacheKeyApplication(appid);
        BaseAgentApp baseAgentApp = RedisUtil.getObject(cacheKeyApplication, BaseAgentApp.class);
        // 缓存为空查数据库
        if (ObjectUtils.isEmpty(baseAgentApp)) {
            SysConfig sysConfig = sysConfigService.getById(appid);
            baseAgentApp = JSONObject.parseObject(sysConfig.getConfigVal(), BaseAgentApp.class);
            LambdaQueryWrapper<AgentAppEntity> gw = AgentAppEntity.gw();
            gw.eq(AgentAppEntity::getAppId,appid);
            AgentAppEntity agentAppEntity = agentAppService.getBaseMapper().selectOne(gw);
            baseAgentApp.setImgUrl(agentAppEntity.getImgUrl());
            baseAgentApp.setName(agentAppEntity.getName());
            // 数据库存在放入缓存
            if (ObjectUtils.isNotEmpty(baseAgentApp)) {
                RedisUtil.set(cacheKeyApplication, baseAgentApp);
            }
        }
        return baseAgentApp;
    }

    public List<AgentAppVO> getList(AgentAppDTO agentAppDTO) {
        if(null == agentAppDTO.getType()){
            throw new BizException("请求参数缺失！");
        }
        return agentAppMapper.getList(agentAppDTO);
    }

    public AgentAppVO getAgentApp(Long activityId) {
        return agentAppMapper.getAgentApp(activityId);
     }

    /**
     * 根据公众号AppId 获取小程序
     * @param officialAppId
     * @return
     */
    public AgentAppEntity getAgentMinAppByOfficialAppId(String officialAppId) {
        AgentAppEntity agentAppEntityOfOfficial = getOne(
                AgentAppEntity.gw()
                        .eq(AgentAppEntity::getAppId, officialAppId)
                        .eq(AgentAppEntity::getIsDeleted, Constants.IS_DELETED.NO)
                        .eq(AgentAppEntity::getIsDefault, 1)
        );
        return getOne(
                AgentAppEntity.gw()
                        .eq(AgentAppEntity::getAgentNo, agentAppEntityOfOfficial.getAgentNo())
                        .eq(AgentAppEntity::getType, Constants.AGENT_APP_TYPE.WX_LITE)
                        .eq(AgentAppEntity::getIsDeleted, Constants.IS_DELETED.NO)
                        .eq(AgentAppEntity::getIsDefault, 1)
        );
    }

    public AgentAppEntity agreement(String appid) {
        String aap = RedisUtil.getString(CS.getPrivacyService(appid));
        if (ObjectUtils.isEmpty(aap)){
            //缓存为空则查库
            AgentAppEntity agentAppEntity = agentAppService.lambdaQuery().eq(AgentAppEntity::getAppId, appid).one();
            if (ObjectUtils.isEmpty(agentAppEntity)){
                throw new BizException("小程序不存在！");
            }
            //放置缓存
            RedisUtil.setString(CS.getPrivacyService(appid), JSON.toJSONString(agentAppEntity));
            return agentAppEntity;
        }else {
            return JSONObject.parseObject(aap, AgentAppEntity.class);
        }

    }

    public AgentAppVO selectOfficial(String appid) {
        AgentAppVO agentAppVO = agentAppMapper.selectOfficial(appid);
        return agentAppVO;
    }
}
